package com.sd.repay.controller;

import com.alibaba.fastjson.JSONObject;
import com.sd.repay.annotation.ClientVersionCheck;
import com.sd.repay.annotation.MerAuthStatusCheck;
import com.sd.repay.auth.ImplRealAUth;
import com.sd.repay.common.CommonResult;
import com.sd.repay.common.Constants;
import com.sd.repay.common.Page;
import com.sd.repay.pojo.ExtractionOrder;
import com.sd.repay.pojo.MerchantUser;
import com.sd.repay.pojo.ProfitDetail;
import com.sd.repay.pojo.SmsInfo;
import com.sd.repay.service.*;
import com.sd.repay.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by sd on 2018/08/21
 * 商户业务控制类
 */
@Controller
@RequestMapping(value = "/merMgr")
public class MerchantController {

    private static final Logger log = LoggerFactory.getLogger(MerchantController.class);

    @Autowired
    private MerchantService merchantService;
    @Autowired
    private AgentService agentService;
    @Autowired
    private ActivateService activateService;
    @Autowired
    private CardManageService cardManageService;
    @Autowired
    private ProfitDetailService profitService;
    @Autowired
    private WithdrawOrderService withdrawOrderService;
    @Autowired
    private SmsService smsService;
    @Autowired
    private ExtractOrderService extractService;

    /**
     * 商户注册（新增商户）
     *
     * @return
     */
    @RequestMapping(value = "/merReg", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8")
    @ResponseBody
    public CommonResult merReg(HttpServletRequest request, @RequestParam Map<String, String> params) {

        log.info("商户注册参数：[{}]" + JsonUtil.objectToJson(params));

        String oemType = params.get("oemType");
        String mobileNo = params.get("mobileNo");
        String merchantName = params.get("merchantName");
        String loginPwd = params.get("loginPwd");
        String confirmLoginPwd = params.get("confirmLoginPwd");
        String smsCode = params.get("smsCode");
        String parentMerNo = params.get("parentMerNo");
        String activateCode = params.get("activateCode");

        try {
            if (StringUtil.isBlank(mobileNo, merchantName, loginPwd, confirmLoginPwd, smsCode)) {
                return CommonResult.build(403, "必要参数不能有空值");
            }
            if (!loginPwd.equals(confirmLoginPwd)) {
                return CommonResult.build(403, "两次密码输入不一致");
            }
            if (!Validator.isMobile(mobileNo)) {
                return CommonResult.build(403, "手机号码不合法");
            }
            if (StringUtils.isBlank(activateCode) && StringUtils.isBlank(parentMerNo)) {
                return CommonResult.build(403, "激活码或者分享人不能都为空");
            }
            if (StringUtils.isNotBlank(activateCode) && StringUtils.isNotBlank(parentMerNo)) {
                return CommonResult.build(403, "激活码和分享人有且仅有一个有值");
            }

            //验证短信验证码
            SmsInfo smsInfo = new SmsInfo();
            smsInfo.setMobiles(mobileNo);
            smsInfo.setSms_business(Constants.SMS_BUSINESS_MERCHANT_REG);
            smsInfo.setVali_code(smsCode);

            smsService.checkValidateCode(smsInfo);
            String smsStatus = smsInfo.getVali_status();
            if (!Constants.SMS_VALI_STATUS_PASS.equals(smsStatus)) {
                return CommonResult.build(403, "短信验证码错误");
            }

            //设置oem类型，默认为“default_repay”
            oemType = StringUtil.isBlank(oemType) ? Constants.DEFAULT_OEM_TYPE : oemType;
            params.put("oemType", oemType);

            //先查询此手机号是否已经注册
            Map<String, Object> oemMerInfo = merchantService.getMerInfoByMobileAndOem(mobileNo, oemType);
            if (null != oemMerInfo && !oemMerInfo.isEmpty()) {
                return CommonResult.build(403, "此手机号已注册");
            }

            //设置商户号
            String merchantNo = WebUtil.nextMerchantNo();
            params.put("merchantNo", merchantNo);

            //设置上级商户信息
            int merGrade = 1;
            String merNode = "", agentNo = "", oneAgentNo = "", agentNode = "";

            //通过分享注册
            if (StringUtils.isNotBlank(parentMerNo)) {
                Map<String, Object> parentMerInfo = merchantService.getMerInfoByMerNo(parentMerNo);
                log.info("商户手机号[{}]注册上级商户信息[{}]", new Object[]{mobileNo, JsonUtil.objectToJson(parentMerInfo)});
                if (null == parentMerInfo) {
                    return CommonResult.build(403, "上级商户不存在");
                }
                merGrade = Integer.parseInt(StringUtil.filterNull(parentMerInfo.get("mer_grade"))) + 1;
                merNode = StringUtil.filterNull(parentMerInfo.get("mer_node")) + "-" + merchantNo;
                agentNo = String.valueOf(parentMerInfo.get("agent_no"));

            } else {
                //通过激活码注册，默认为顶级商户
                parentMerNo = "0";
                merNode = merchantNo;

                Map<String, Object> activateMap = activateService.getActivateByCode(activateCode);
                log.info("商户手机号[{}]注册商户激活码[{}]对应激活码信息[{}]", new Object[]{mobileNo, activateCode, JsonUtil.objectToJson(activateMap)});
                if (activateMap == null || activateCode.isEmpty()) {
                    return CommonResult.build(403, "激活码不存在");
                }
                String codeStatus = StringUtil.filterNull(activateMap.get("status"));
                String codeCanUse = StringUtil.filterNull(activateMap.get("can_use"));
                if (!Constants.ACTIVATE_STATUS_ALLOT.equals(codeStatus) || !Constants.ACTIVATE_CAN_USE.equals(codeCanUse)) {
                    return CommonResult.build(403, "激活码无效");
                }
                agentNo = String.valueOf(activateMap.get("agent_no"));
            }
            //设置代理商信息
            Map<String, Object> agentMap = agentService.getAgentInfoByAgentNo(agentNo);
            log.info("商户手机号[{}]注册对应代理商信息[{}]", new Object[]{mobileNo, activateCode, JsonUtil.objectToJson(agentMap)});
            if (null == agentMap || agentMap.isEmpty()) {
                return CommonResult.build(403, "所属代理不存在");
            }
            oneAgentNo = StringUtil.filterNull(agentMap.get("one_agent_no"));
            agentNode = StringUtil.filterNull(agentMap.get("agent_node"));

            params.put("parentMerNo", parentMerNo);
            params.put("merGrade", String.valueOf(merGrade));
            params.put("merNode", merNode);

            params.put("agentNo", agentNo);
            params.put("oneAgentNo", oneAgentNo);
            params.put("agentNode", agentNode);

            //设置密码
            loginPwd = Md5Util.MD5Encode(loginPwd, "UTF-8", false);
            params.put("loginPwd", loginPwd);

            //保存商户
            int count = merchantService.addMerchantInfo(params);
            log.info("商户手机号[{}]注册商户影响的行数：[{}]", new Object[]{mobileNo, count});
            if (count < 1) {
                return CommonResult.build(403, "商户注册失败");
            }
            return CommonResult.ok(merchantNo);

        } catch (Exception e) {
            e.printStackTrace();
            log.info("商户手机号[{}]注册异常[{}]", new Object[]{mobileNo, e});
            return CommonResult.build(403, "商户注册失败，请稍候再试");
        }
    }


    /**
     * 实名认证（新增或修改结算卡信息）
     *
     * @return
     */
    @RequestMapping(value = "/merSettleAuth", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8")
    @ResponseBody
    public CommonResult merSettleAuth(HttpServletRequest request, @RequestParam Map<String, String> params) {

        MerchantUser currUser = WebUtil.getCurrMerchantUser();
        String merchantNo = currUser.getMerchantNo();
        String merMobileNo = currUser.getMobileNo();
        log.info("商户号：[{}]实名认证参数：[{}]", new Object[]{merchantNo, JsonUtil.objectToJson(params)});

        try {
            String oemType = params.get("oemType");
            String realName = params.get("realName");
            String mobileNo = params.get("mobileNo");
            String idCardNo = params.get("idCardNo");
            String accountNo = params.get("accountNo");
            String bankNo = params.get("bankNo");
            String branchBankName = params.get("branchBankName");
            String province = params.get("province");
            String city = params.get("city");
            String address = params.get("address");

            String idFontFileStr = params.get("idFont");
            String idBackFileStr = params.get("idBack");
            String idHandFileStr = params.get("idHand");
            String bankFileStr = params.get("bank");

            oemType = StringUtil.isBlank(oemType) ? Constants.DEFAULT_OEM_TYPE : oemType;
            params.put("oemType", oemType);

            if (StringUtil.isBlank(realName, mobileNo, idCardNo, accountNo, province, city, address)) {
                return CommonResult.build(403, "必要参数不能有空值");
            }
            //校验是否是结算卡
            Map<String, Object> posCardInfo = cardManageService.getPosCardInfoByAccountNo(accountNo);
            log.info(accountNo + "系统卡bin表对应信息：" + JsonUtil.objectToJson(posCardInfo));
            if (null == posCardInfo || posCardInfo.isEmpty()) {
                return CommonResult.build(403, "暂不支持此银行卡");
            }
            String posBankName = String.valueOf(posCardInfo.get("bank_name"));
            String posCardType = String.valueOf(posCardInfo.get("card_type"));
            String posBankNo = String.valueOf(posCardInfo.get("bank_no"));

            if (StringUtil.isBlank(posBankName, posCardType, posBankNo)) {
                return CommonResult.build(403, "暂不支持此银行卡");
            }
            if (!posCardType.trim().equals("借记卡")) {
                return CommonResult.build(403, "此卡非借记卡");
            }

            if (!Validator.isMobile(mobileNo)) {
                return CommonResult.build(403, "手机号码不合法");
            }
            if (!IdcardUtils.validateCard(idCardNo)) {
                return CommonResult.build(403, "身份证不合法");
            }

            Map<String, String> authparams = new HashMap<>();
            authparams.put("authType", Constants.AUTH_TYPE_THREE);
            authparams.put("realName", realName);
            authparams.put("idCardNo", idCardNo);
            authparams.put("accountNo", accountNo);
            CommonResult authRes = ImplRealAUth.toRealAuth(authparams);
            if (authRes.getStatus() != 200) {
                return CommonResult.build(403, "银行卡信息与身份信息不匹配");
            }

            Map<String, String> saveCardMap = new HashMap<>();
            String cardNo = WebUtil.nextUniqueSeqNo("t_card_manage", "", 15);
            saveCardMap.put("merchantNo", merchantNo);
            saveCardMap.put("cardNo", cardNo);
            saveCardMap.put("idCardNo", idCardNo);
            saveCardMap.put("mobileNo", mobileNo);
            saveCardMap.put("accountNo", accountNo);
            saveCardMap.put("accountName", realName);
            saveCardMap.put("cardType", Constants.CARD_TYPE_DEBIT);
            saveCardMap.put("isSettleCard", "1");
            saveCardMap.put("settleBankNo", posBankNo);
            saveCardMap.put("bankName", posBankName);
            saveCardMap.put("bankNo", bankNo);
            saveCardMap.put("province", province);
            saveCardMap.put("city", city);
            saveCardMap.put("statementDate", "0");
            saveCardMap.put("repaymentDate", "0");

            //先查询当前身份证号的用户是否已添加结算卡
            Map<String, Object> settleCardInfo = cardManageService.getSettleCardInfoByIdCard(idCardNo);
            int count = 0;
            //没有添加结算卡
            if (settleCardInfo == null || settleCardInfo.isEmpty()) {
                if (StringUtil.isBlank(idFontFileStr, idBackFileStr, idHandFileStr, bankFileStr)) {
                    return CommonResult.build(403, "资质照片不能有空");
                }
                String dirPath = WebUtil.getMerInfoFilePath(merchantNo);

                if(WebUtil.makeFiles(dirPath)){
                    File file=new File(dirPath);
                    file.mkdir();
                }

                //身份证正面照上传
                String idFontFilePath = dirPath + File.separator + "idFont.png";
                boolean fileFlag = Base64ImageUtil.Base64ToImage(idFontFileStr, idFontFilePath);
                if (!fileFlag) {
                    return CommonResult.build(403, "身份证正面照上传失败");
                }
                //身份证反面照上传
                String idBackFilePath = dirPath + File.separator + "idBack.png";
                fileFlag = Base64ImageUtil.Base64ToImage(idBackFileStr, idBackFilePath);
                if (!fileFlag) {
                    return CommonResult.build(403, "身份证正面照上传失败");
                }
                //手持身份证照上传
                String idHandFilePath = dirPath + File.separator + "idHand.png";
                fileFlag = Base64ImageUtil.Base64ToImage(idHandFileStr, idHandFilePath);
                if (!fileFlag) {
                    return CommonResult.build(403, "手持身份证照上传失败");
                }
                //手持身份证照上传
                String bankFilePath = dirPath + File.separator + "bank.png";
                fileFlag = Base64ImageUtil.Base64ToImage(bankFileStr, bankFilePath);
                if (!fileFlag) {
                    return CommonResult.build(403, "银行卡照上传失败");
                }
                JSONObject merFileJson = new JSONObject();
                merFileJson.put("idFont", idFontFilePath);
                merFileJson.put("idBack", idBackFilePath);
                merFileJson.put("idHand", idHandFilePath);
                merFileJson.put("bank", bankFilePath);
                String merFilePath = merFileJson.toJSONString();

                saveCardMap.put("filePath", merFilePath);
                saveCardMap.put("isUpdateMerAuth", "true");
                saveCardMap.put("address", address);
                count = cardManageService.addCardInfo(saveCardMap);
                log.info("商户号:{}添加结算卡号：{}影响的行数", new Object[]{merchantNo, accountNo, count});
                if (count < 1) {
                    return CommonResult.build(403, "操作失败，请稍候再试");
                }
            } else {
                //修改结算卡

                //判断卡号是否已修改
                String oldSettleCardNo = String.valueOf(settleCardInfo.get("card_no"));
                String oldAccountNo = String.valueOf(settleCardInfo.get("account_no"));
                if (accountNo.equals(oldAccountNo)) {
                    return CommonResult.build(403, "修改结算卡不能是当前结算卡");
                }
                count = cardManageService.addCardInfo(saveCardMap);
                log.info("商户号:{}添加结算卡号：{}影响的行数", new Object[]{merchantNo, accountNo, count});
                if (count > 0) {
                    cardManageService.updateSettleStatus(oldSettleCardNo, "0");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("商户号:{}实名认证异常{}", new Object[]{merchantNo, e});
            return CommonResult.build(403, "操作失败，请稍候再试");
        }
        return CommonResult.ok();
    }


    /**
     * 商户收益汇总
     *
     * @return
     */
    @RequestMapping(value = "/profitSummary", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8")
    @ResponseBody
    public CommonResult profitSummary(HttpServletRequest request, @RequestParam Map<String, String> params) {

        String merchantNo = WebUtil.getCurrMerchantUser().getMerchantNo();
        log.info("商户号[{}]收益汇总参数[{}]", new Object[]{merchantNo, JsonUtil.objectToJson(params)});

        Map<String, String> resMap = new HashMap<>();
        try {

            //获取总收益金额
            String totalProfitAmount = profitService.getTotalProfitAmountByMer(Constants.MER_TYPE_MERCHANT, merchantNo);
            resMap.put("totalProfitAmount", StringUtils.isBlank(totalProfitAmount) ? "0.00" : totalProfitAmount);

            //获取总结算金额
            String totalSettledAmount = withdrawOrderService.getSettledAmountByMer(Constants.MER_TYPE_MERCHANT, merchantNo);
            resMap.put("totalSettledAmount", StringUtils.isBlank(totalSettledAmount) ? "0.00" : totalSettledAmount);

            //获取可提现金额和冻结金额
            resMap.putAll(profitService.getMerTypeBalance(Constants.MER_TYPE_MERCHANT, merchantNo));

            return CommonResult.ok(resMap);

        } catch (Exception e) {
            e.printStackTrace();
            log.info("商户号[{}]收益汇总异常[{}]", new Object[]{merchantNo, e});
            return CommonResult.build(403, "操作失败，请稍候再试");
        }
    }


    /**
     * 商户收益明细
     *
     * @return
     */
    @RequestMapping(value = "/profitDetail", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8")
    @ResponseBody
    public CommonResult profitDetail(HttpServletRequest request, @RequestParam Map<String, String> params) {
        String startTime = params.get("startTime");
        String endTime = params.get("endTime");
        String pageNo = params.get("pageNo");
        String pageSize = params.get("pageSize");

        if (StringUtil.isBlank(startTime, endTime, pageNo, pageSize)) {
            CommonResult result = new CommonResult(403, "必要的参数不能为空", null);
            log.error(result.getStatus() + "|" + result.getMsg());
            return result;
        }

        String merchantNo = WebUtil.getCurrMerchantUser().getMerchantNo();
        log.info("商户号[{}]收益明细参数[{}]", new Object[]{merchantNo, JsonUtil.objectToJson(params)});

        try {

            Page<ProfitDetail> profitDetails = profitService.getProfitDetailPageByMer(Constants.MER_TYPE_MERCHANT, merchantNo, startTime, endTime, Integer.parseInt(pageNo), Integer.parseInt(pageSize));
            List<Map<String, String>> resMapList = new ArrayList<>();

            Map<String, String> map;
            for (ProfitDetail detail : profitDetails.getData()) {
                map = new HashMap<>();
                map.put("sourceMerType", detail.getSourceMerType());
                map.put("sourceMerNo", detail.getSourceMerNo());
                map.put("serviceType", detail.getServiceType());
                map.put("transAmount", String.valueOf(detail.getTransAmount()));
                map.put("profitTime", DateUtil.format(detail.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
                map.put("incomeStatus", detail.getIncomeStatus());

                resMapList.add(map);
            }
            return CommonResult.ok(resMapList);

        } catch (Exception e) {
            e.printStackTrace();
            log.info("商户号[{}]收益明细异常[{}]", new Object[]{merchantNo, e});
            return CommonResult.build(403, "操作失败，请稍候再试");
        }
    }


    /**
     * 商户提现记录
     *
     * @return
     */
    @MerAuthStatusCheck
    @ClientVersionCheck
    @RequestMapping(value = "/cashRecord", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8")
    @ResponseBody
    public CommonResult cashRecord(HttpServletRequest request, @RequestParam Map<String, String> params) {

        String startTime = params.get("startTime");
        String endTime = params.get("endTime");
        String pageNo = params.get("pageNo");
        String pageSize = params.get("pageSize");

        if (StringUtil.isBlank(startTime, endTime, pageNo, pageSize)) {
            CommonResult result = new CommonResult(403, "必要的参数不能为空", null);
            log.error(result.getStatus() + "|" + result.getMsg());
            return result;
        }
        String merchantNo = WebUtil.getCurrMerchantUser().getMerchantNo();
        log.info("商户号[{}]提现记录参数[{}]", new Object[]{merchantNo, JsonUtil.objectToJson(params)});
        try {
            Page<ExtractionOrder> cashRecords = extractService.getExtractionOrderPageByMer(Constants.MER_TYPE_MERCHANT, merchantNo, startTime, endTime, Integer.parseInt(pageNo), Integer.parseInt(pageSize));
            return CommonResult.ok(cashRecords == null ? new ArrayList<>() : cashRecords.getData());

        } catch (Exception e) {
            e.printStackTrace();
            log.info("商户号[{}]提现记录异常[{}]", new Object[]{merchantNo, e});
            return CommonResult.build(403, "操作失败，请稍候再试");
        }
    }
}
